Note that there are no "official" definitions for these terms, so different texts and implementations associate slightly different characteristics with each primitive.
original Dijkstra | P() | V() |
Tanenbaum | down() | up() |
POSIX | sem_wait() | sem_post() |
Silberschatz | wait() | signal() |
operation | while (s==0) {wait}; s-- | s++ |
The choice of threads being signaled depends on the implementation. Most implementations make no guarantees.
Condition variables are not counters (i.e., unlike semaphors). Signals do not accumulate. If there is nobody waiting for a signal, the signal is lost.
property | lock | semaphore | condition variable |
---|---|---|---|
method that blocks calling thread (ANSI) | acquire() , mutex_lock()
| sem_wait()
| pthread_cond_wait()
|
method that releases | mutex_unlock() (same thread)
| sem_post() (same or other thread)
| pthread_cond_signal() (other thread)
|
method that probes without blocking | pthread_mutex_trylock()
| sem_trywait()
| not available |
behavior of first thread to reach wait | doesn't block | doesn't block unless semaphore initialized to zero | blocks |
data members | List *threads; /* waiting threads */ boolean locked; | List *threads; unsigned int count; | List *threads; Lock *mutex; |
notifyAll
in Java.
Thus, the thread calling the wait()
often looks
something like
lock to protect variables; while (1) { wait (until work/message/condition/event arrives, possibly from one of several sources; unlock mutex while waiting); get new work, protected by mutex; }This is sometimes called a worker thread.
Any of the threads that are sources for work then do
while (1) { read(); /* some blocking operation on a channel/file/network socket */ get lock; put work on some queue protected by lock; signal to worker thread; /* we got work for you! */ release lock; }
Last updated by Henning Schulzrinne